package me.edzh.spring.bootstrap.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import lombok.extern.log4j.Log4j;
import me.edzh.spring.bootstrap.utils.exception.ServiceException;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Log4j
public class JSONUtil {
    public static <T> T parseJson(String json, Class<T> cls) {
        if (json == null) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "null json");
        }
        try {
            return ObjectMapperFactory.getObjectMapper().readValue(json, cls);
        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 解析出错", t);
        }
    }

    public static <T> T parseJson(byte[] json, Class<T> cls) {
        if (json == null) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "null json");
        }
        try {
            return ObjectMapperFactory.getObjectMapper().readValue(json, cls);
        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 解析出错", t);
        }
    }

    public static <T> T parseJson(String json, JavaType cls) {
        if (json == null) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "null json");
        }
        try {
            return ObjectMapperFactory.getObjectMapper().readValue(json, cls);
        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 解析出错", t);
        }
    }

    public static <T> T parseJson(String json, TypeReference<?> cls) {
        if (json == null) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "null json");
        }
        try {
            return ObjectMapperFactory.getObjectMapper().readValue(json, cls);
        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 解析出错", t);
        }
    }
    public static <T> T parseJson(Map json, TypeReference<?> cls) {
        if (json == null) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "null json");
        }
        try {
            return ObjectMapperFactory.getObjectMapper().convertValue(json, cls);
        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 解析出错", t);
        }
    }

    @SuppressWarnings("rawtypes")
    public static <T> T parseJson(Map json, Class<T> cls) {
        if (json == null) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "null json");
        }

        for (Class directlyConvertType : DIRECTLY_CONVERT_TYPES) {
            if (directlyConvertType.isAssignableFrom(cls)) return (T)json;
        }

        try {
            return ObjectMapperFactory.getObjectMapper().convertValue(json, cls);
        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 解析出错", t);
        }
    }

    public static String toJson(Object obj) {
        try {
            return ObjectMapperFactory.getObjectMapper().writeValueAsString(obj);

        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 序列化出错", t);
        }
    }

    /**
     * 将<String, String>形式的json转化为HashMap
     * @param json 要求是<String, String>形式
     */
    public static HashMap<String, String> jsonToMap(String json) {
        try {
            log.info("JSON parse to map:" + json);
            return ObjectMapperFactory.getObjectMapper().readValue(json, HashMap.class);
        } catch (Throwable t) {
            log.info("Json解析出错，源字符串：" + json, t);
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 解析出错", t);
        }
    }

    public static Map<String, Object> objectToMap(Object object) {
        try {
            return ObjectMapperFactory.getObjectMapper().convertValue(object, HashMap.class);

        } catch (Throwable t) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "json 转换出错", t);
        }
    }

    private final static List<Class> DIRECTLY_CONVERT_TYPES = Arrays.asList(
            Map.class,
            Number.class,
            String.class
    );
}
